# -*- coding: utf_8 -*-
# @Time : 2021/8/31 0031 15:52
# @Author : yh
# @Remark : 待修库
import copy
import time
import logging
import os
from typing import List

from mxsoftpy import Server
from mxsoftpy.exception import DataError, DBError

from db.common.VideoManage.VideoQuality.conf import TestItemsDB, VideoDeviceDB
from db.common.VideoManage.VideoQuality.repair_warehouse import RepairDB
from db.common.VideoManage.VideoQuality.video import VideoDB
from model.common.VideoManage.VideoQuality.repair_warehouse import RepairSelectModel
from model.common.VideoManage.VideoQuality.video import VideoRepairCreateModel, VideoRepairDeleteModel
from utils.conf.mxconfig import MxConfig
from utils.public.export_execl import ExportExecl
from utils.public.params_method import update_select_params, paging_data, get_pagination_params


class RepairServer(Server):

    def __init__(self):
        super().__init__()
        self.__video_cache = dict()  # 视频详情缓存
        self.__device_type: dict = VideoDeviceDB('DeviceType').use_keys([])  # 所有设备类型字典

    def _export_data(self, data, headline_dict):
        """
        转换成导出excl所需格式
        param: data 需要转换的列表
        param：test_name_dict 拼接headline
        """

        data_dict = {
            "header": "待修库",
            "headline": {
                "id": "序号",
                "device_name": "设备名称",
                "device_ip": "网络地址",
                **headline_dict,
                # "repair_personnel": "操作人",
                # "repair_time": "操作时间",
            },
            "data": data
        }
        file_name = "repair_" + str(int(time.time())) + ".xlsx"
        return data_dict, file_name

    def create(self, videos: str, **create_data) -> List[str]:
        """
        添加视频到待修库
        :param videos: 要添加的视频，多个使用分号分割
        :param create_data: 新增的待修库数据
        """
        error_list = []  # 存储所有添加失败的视频
        for video_code in videos.split(';'):
            try:
                RepairDB().update(video_code, VideoRepairCreateModel(repair_personnel=create_data['personnel']))
            except DBError as e:
                logging.error('添加待修库失败, 视频code：%s，错误详情：%s' % (video_code, str(e)))
                error_list.append(video_code)
        if error_list:
            raise DataError(f"视频{error_list}添加至待修库失败")
        return videos.split(';')

    def delete(self, videos: str, **delete_data) -> list:
        """
        从待修库删除视频，多个使用分号分割
        :param videos: 视频code
        """
        error_list = []  # 存储所有添加失败的视频
        for video_code in videos.split(';'):
            try:

                RepairDB().delete(video_code, VideoRepairDeleteModel())
            except DBError as e:
                logging.error('删除待修库失败, 视频code：%s，错误详情：%s' % (video_code, str(e)))
                error_list.append(video_code)
        if error_list:
            raise DataError(f"视频{error_list}从待修库删除失败")
        return videos.split(';')

    def __select_video_from_cache(self, video_code: str) -> dict:
        """
        从缓存获取视频详情（没有缓存就从数据库获取）
        :param video_code: 要获取的视频code
        """
        if self.__video_cache.get(video_code):
            return self.__video_cache[video_code]
        else:
            self.__video_cache[video_code] = VideoDB().retrieve(video_code)
            return self.__video_cache[video_code]

    def select(self, **select_query: "RepairSelectModel"):
        """
        查询待修库
        :param select_query: 查询参数，详情见RepairSelectModel类
        """
        export_code = select_query.get('export_code')
        select_data = RepairSelectModel(**select_query).dict()

        video_query = {
            'repair_state': 1,  # 待修标识
            'name__like': '*%s*' % select_data['select_param'],
            'device_ip__like': '*%s*' % select_data['select_param'],
            'default_expression': '0 and 1 and ( 2 or 3)'
        }

        videos = VideoDB().simple_list(**update_select_params(video_query))
        test_items_dict = TestItemsDB('TestItems').list(['name'])
        test_list = []
        headline_dict = {}
        for k, v in test_items_dict.items():
            test_list.append({'test_code': k, 'test_state': v.get(k) or 0, 'test_name': v.get('name')})
            headline_dict[v['name']] = v['name']
        res_list = list()

        i = 0  # 序号
        for code, value in videos.items():
            err_test_list = value['running_error'].split(';')
            normal_test_list = value['running_normal'].split(';')
            fail_test_list = value['running_fail'].split(';')
            test_data = copy.deepcopy(test_list)
            for test in test_data:
                if test['test_code'] in err_test_list:
                    test['test_state'] = 3
                elif test['test_code'] in normal_test_list:
                    test['test_state'] = 1
                elif test['test_code'] in fail_test_list:
                    test['test_state'] = 2
                else:
                    test['test_state'] = 0

            i += 1
            res_dict = {
                'id': i,
                'video_code': code,
                'device_name': value['name'],
                'device_ip': value['device_ip'],
                'device_type_name': self.__device_type.get(value['device_type_code'])['name'],
                'repair_state': value['repair_state'],
                'vendor': value['vendor'],
                'test_data': test_data,
                'repair_personnel': value['repair_personnel'],
                'repair_time': time.strftime("%Y-%m-%d %H:%M",
                                             time.localtime(value['repair_time']))}
            if export_code == "1":
                for test_dict in test_data:
                    state_dict = {0: "未检测", 1: "正常", 2: "检测失败", 3: "故障"}
                    res_dict[test_dict['test_name']] = state_dict.get(test_dict['test_state']) \
                                                       or state_dict.get(0)
            res_list.append(res_dict)

        if export_code == "1":
            data_dict, file_name = self._export_data(res_list, headline_dict)
            path = MxConfig.TMP_DIR + file_name
            execl_path = os.sep + "tmp" + os.sep + file_name

            if data_dict['data']:
                try:
                    ExportExecl().data_process(data_dict)(path)
                    return {'execl_path': execl_path}
                except:
                    logging.error("导出excle出错")
                    raise DataError("导出excle出错")
            else:
                raise DataError("数据为空")

        return paging_data(res_list, **get_pagination_params(select_query))
